/*
Copyright 2018-2024 New Vector Ltd.
Copyright 2015 OpenMarket Ltd

SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
 */

#import "MXKEventDetailsView.h"

#import "NSBundle+MatrixKit.h"

#import "MXKConstants.h"

#import "MXKSwiftHeader.h"

@interface MXKEventDetailsView ()
{
    /**
     The displayed event
     */
    MXEvent *mxEvent;
    
    /**
     The matrix session.
     */
    MXSession *mxSession;
}
@end

@implementation MXKEventDetailsView

+ (UINib *)nib
{
    // Check whether a nib file is available
    NSBundle *mainBundle = [NSBundle mxk_bundleForClass:self.class];
    
    NSString *path = [mainBundle pathForResource:NSStringFromClass([self class]) ofType:@"nib"];
    if (path)
    {
        return [UINib nibWithNibName:NSStringFromClass([self class]) bundle:mainBundle];
    }
    return [UINib nibWithNibName:NSStringFromClass([MXKEventDetailsView class]) bundle:[NSBundle mxk_bundleForClass:[MXKEventDetailsView class]]];
}

- (void)awakeFromNib
{
    [super awakeFromNib];
    
    // Localize string
    [_redactButton setTitle:[VectorL10n redact] forState:UIControlStateNormal];
    [_redactButton setTitle:[VectorL10n redact] forState:UIControlStateHighlighted];
    [_closeButton setTitle:[VectorL10n close] forState:UIControlStateNormal];
    [_closeButton setTitle:[VectorL10n close] forState:UIControlStateHighlighted];
}

- (instancetype)initWithEvent:(MXEvent*)event andMatrixSession:(MXSession*)session
{
    self = [[[self class] nib] instantiateWithOwner:nil options:nil].firstObject;
    if (self)
    {
        mxEvent = event;
        mxSession = session;
        
        [self setTranslatesAutoresizingMaskIntoConstraints: NO];
        
        // Disable redact button by default
        _redactButton.enabled = NO;
        
        if (mxEvent)
        {
            NSMutableDictionary *eventDict = [NSMutableDictionary dictionaryWithDictionary:mxEvent.JSONDictionary];
            
            // Remove event type added by SDK
            [eventDict removeObjectForKey:@"event_type"];
            // Remove null values and empty dictionaries
            for (NSString *key in eventDict.allKeys)
            {
                if ([[eventDict objectForKey:key] isEqual:[NSNull null]])
                {
                    [eventDict removeObjectForKey:key];
                }
                else if ([[eventDict objectForKey:key] isKindOfClass:[NSDictionary class]])
                {
                    NSDictionary *dict = [eventDict objectForKey:key];
                    if (!dict.count)
                    {
                        [eventDict removeObjectForKey:key];
                    }
                    else
                    {
                        NSMutableDictionary *updatedDict = [NSMutableDictionary dictionaryWithDictionary:dict];
                        for (NSString *subKey in dict.allKeys)
                        {
                            if ([[dict objectForKey:subKey] isEqual:[NSNull null]])
                            {
                                [updatedDict removeObjectForKey:subKey];
                            }
                        }
                        [eventDict setObject:updatedDict forKey:key];
                    }
                }
            }
            
            // Set text view content
            NSError *error;
            NSData *jsonData = [NSJSONSerialization dataWithJSONObject:eventDict
                                                               options:NSJSONWritingPrettyPrinted
                                                                 error:&error];
            _textView.text = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
            
            // Check whether the user can redact this event
            // Do not allow to redact the event that enabled encryption (m.room.encryption)
            // because it breaks everything
            if (!mxEvent.isRedactedEvent && mxEvent.eventType != MXEventTypeRoomEncryption)
            {
                // Here the event has not been already redacted, check the user's power level
                MXRoom *mxRoom = [mxSession roomWithRoomId:mxEvent.roomId];
                if (mxRoom)
                {
                    MXWeakify(self);
                    [mxRoom state:^(MXRoomState *roomState) {
                        MXStrongifyAndReturnIfNil(self);

                        MXRoomPowerLevels *powerLevels = [roomState powerLevels];
                        NSInteger userPowerLevel = [roomState powerLevelOfUserWithUserID:self->mxSession.myUser.userId];
                        if (powerLevels.redact)
                        {
                            if (userPowerLevel >= powerLevels.redact)
                            {
                                self.redactButton.enabled = YES;
                            }
                        }
                        else if (userPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsMessage:kMXEventTypeStringRoomRedaction])
                        {
                            self.redactButton.enabled = YES;
                        }
                    }];
                }
            }
        }
        else
        {
            _textView.text = nil;
        }
        
        // Hide potential activity indicator
        [_activityIndicator stopAnimating];
    }
    
    return self;
}

- (void)dealloc
{
    mxEvent = nil;
    mxSession = nil;
}

#pragma mark - Actions

- (IBAction)onButtonPressed:(id)sender
{
    if (sender == _redactButton)
    {
        MXRoom *mxRoom = [mxSession roomWithRoomId:mxEvent.roomId];
        if (mxRoom)
        {
            [_activityIndicator startAnimating];
            [mxRoom redactEvent:mxEvent.eventId reason:nil success:^{
                
                [self->_activityIndicator stopAnimating];
                [self removeFromSuperview];
                
            } failure:^(NSError *error) {
                
                MXLogDebug(@"[MXKEventDetailsView] Redact event (%@) failed", self->mxEvent.eventId);
                
                // Notify MatrixKit user
                NSString *myUserId = mxRoom.mxSession.myUser.userId;
                [[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:error userInfo:myUserId ? @{kMXKErrorUserIdKey: myUserId} : nil];
                
                [self->_activityIndicator stopAnimating];
                
            }];
        }
        
    }
    else if (sender == _closeButton)
    {
        [self removeFromSuperview];
    }
}

@end
